package top.ljlgithub.api.service.impl;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.ljlgithub.api.bean.Menu;
import top.ljlgithub.api.bean.Right;
import top.ljlgithub.api.bean.TreeBO;
import top.ljlgithub.api.mapper.RightMapper;
import top.ljlgithub.api.service.RightService;

import java.util.*;

/**
 * @ClassName
 * @Description TODO
 * @Author L1470
 * @Date 2021/5/6 7:19
 * @Version 1.0
 **/
@Service
public class RightServiceImpl implements RightService {
    @Autowired
    RightMapper rightMapper;
    ArrayList<String> sb = new ArrayList<>();

    @Override
    public List<Right> getRightList() {
        return rightMapper.getRightList();
    }

    @Override
    public List<TreeBO> selectNodeTreeByPid() {
        List<Right> nodeList = getRightList();
        List<TreeBO> treeList = new ArrayList<>();
        Map<Integer, List<Right>> nodeLevelMap = new HashMap<>();
        nodeList.forEach(node -> {
            Integer level = node.getLevel();
            if (nodeLevelMap.containsKey(level)) {
                nodeLevelMap.get(level).add(node);
            } else {
                List<Right> testCaseNodes = new ArrayList<>();
                testCaseNodes.add(node);
                nodeLevelMap.put(node.getLevel(), testCaseNodes);
            }
        });
        List<Right> rootNodes = Optional.ofNullable(nodeLevelMap.get(0)).orElse(new ArrayList<>());
        rootNodes.forEach(rootNode -> treeList.add(buildNodeTree(nodeLevelMap, rootNode)));
        updatePid(treeList);
        return treeList;
    }

    /**
     * 递归构建节点树
     * @param nodeLevelMap
     * @param rootNode
     * @return
     */
    private TreeBO buildNodeTree(Map<Integer, List<Right>> nodeLevelMap, Right rootNode) {

        TreeBO nodeTree = new TreeBO();
        BeanUtils.copyProperties(rootNode, nodeTree);
        nodeTree.setAuthName(rootNode.getAuthName());

        List<Right> lowerNodes = nodeLevelMap.get(rootNode.getLevel() + 1);
        if (lowerNodes == null) {
            return nodeTree;
        }

        List<TreeBO> children = Optional.ofNullable(nodeTree.getChildren()).orElse(new ArrayList<>());

        lowerNodes.forEach(node -> {
            if (node.getPid() != null && node.getPid().equals(rootNode.getId())) {
                children.add(buildNodeTree(nodeLevelMap, node));
                nodeTree.setChildren(children);
            }
        });
        return nodeTree;
    }

    private void updatePid(List<TreeBO> treeList){

        if (treeList != null && treeList.size() != 0) {
            for (TreeBO treeBO : treeList) {
                if (treeBO.getLevel() == 0){
                    sb.clear();
                }
                if (treeBO.getLevel() == 1 && sb.size() == 2){
                    sb.remove(0);
                }
                if (treeBO.getLevel() > 1){
                    treeBO.setPid(String.join(",",sb));
                }
                if (treeBO.getChildren() != null){
                    sb.add(0,treeBO.getId());
                }
                updatePid(treeBO.getChildren());
            }
        }
    }

    @Override
    public List<Right> getMenuList() {
        return rightMapper.getMenuList();
    }

    @Override
    public List<Menu> getMenuTree() {
        List<Right> nodeList = getMenuList();
        List<Menu> treeList = new ArrayList<>();
        Map<Integer, List<Right>> nodeLevelMap = new HashMap<>();
        nodeList.forEach(node -> {
            Integer level = node.getLevel();
            if (nodeLevelMap.containsKey(level)) {
                nodeLevelMap.get(level).add(node);
            } else {
                List<Right> testCaseNodes = new ArrayList<>();
                testCaseNodes.add(node);
                nodeLevelMap.put(node.getLevel(), testCaseNodes);
            }
        });
        List<Right> rootNodes = Optional.ofNullable(nodeLevelMap.get(0)).orElse(new ArrayList<>());
        rootNodes.forEach(rootNode -> treeList.add(buildMenuTree(nodeLevelMap, rootNode)));
        updateOrder(treeList);
        return treeList;
    }
    private Menu buildMenuTree(Map<Integer, List<Right>> nodeLevelMap, Right rootNode) {

        Menu nodeTree = new Menu();
        BeanUtils.copyProperties(rootNode, nodeTree);
        nodeTree.setAuthName(rootNode.getAuthName());

        List<Right> lowerNodes = nodeLevelMap.get(rootNode.getLevel() + 1);
        if (lowerNodes == null) {
            return nodeTree;
        }

        List<Menu> children = Optional.ofNullable(nodeTree.getChildren()).orElse(new ArrayList<>());

        lowerNodes.forEach(node -> {
            if (node.getPid() != null && node.getPid().equals(rootNode.getId())) {
                children.add(buildMenuTree(nodeLevelMap, node));
                nodeTree.setChildren(children);
            }
        });
        return nodeTree;
    }

    private void updateOrder(List<Menu> treeList){
        if (treeList != null && treeList.size() != 0) {
            for (int i = 0; i < treeList.size(); i++) {
                Menu menu = treeList.get(i);
                menu.setOrder(i+1);
                updateOrder(menu.getChildren());
            }
        }
    }
}
